﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace ParticleEditor
{
    public partial class Form1 : Form
    {
        public ManagedDirect3D mD3D;
        public ManagedTextureManager mTM;
        bool mouseDown = false;
        string sFile;
        string workingDirectory;
        
        int imageTest = -1;
        Emitter emits = new Emitter();

        bool looping;
        public bool Looping
        {
            get { return looping; }
            set { looping = value; }
        }

        private void SetEmitterID(int iD)
        {
            emits.NEmitterID = iD;
        }

        public Form1()
        {
            looping = true;
            InitializeComponent();
            comboBoxEmitterShape.SelectedIndex = 0;
            mD3D = ManagedDirect3D.Instance;
            mTM = ManagedTextureManager.Instance;

            mD3D.InitManagedDirect3D(splitContainer2.Panel2);
            mD3D.InitManagedDirect3D(splitContainer2.Panel1);

            mTM.InitManagedTextureManager(mD3D.Device, mD3D.Sprite);

            FolderBrowserDialog fBD = new FolderBrowserDialog();
            fBD.Description = "Choose Directory to Work From";
            if (DialogResult.OK == fBD.ShowDialog())
            {
                workingDirectory = fBD.SelectedPath;
            }
        }

        DateTime prevTime = DateTime.Now;
        public new void Update()
        {
            TimeSpan fElapsedTime = DateTime.Now - prevTime;

            prevTime = DateTime.Now;

            EmitterInfo(emits, imageTest);

            emits.Update((float)fElapsedTime.TotalSeconds);
        }

        public void Render()
        {
            mD3D.Clear(splitContainer2.Panel2, Color.White);
            mD3D.DeviceBegin();
            mD3D.SpriteBegin();

            if (imageTest != -1)
            {
                emits.Render();
            }

            mD3D.SpriteEnd();
            mD3D.DeviceEnd();
            mD3D.Present(splitContainer2.Panel2);

            mD3D.Clear(splitContainer2.Panel1, Color.White);
            mD3D.DeviceBegin();
            mD3D.SpriteBegin();

            if (imageTest != -1)
            {
                mTM.Draw(imageTest, 0, 0, 1, 1, Rectangle.Empty, 0, 0, 0.0f, Color.White);
            }

            mD3D.SpriteEnd();
            mD3D.DeviceEnd();
            mD3D.Present(splitContainer2.Panel1);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            looping = false;
        }

        private void buttonColorStart_Click(object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                numericUpDownCStartA.Value = dlg.Color.A;
                numericUpDownCStartR.Value = dlg.Color.R;
                numericUpDownCStartG.Value = dlg.Color.G;
                numericUpDownCStartB.Value = dlg.Color.B;
            }
        }

        private void buttonColorEnd_Click(object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                numericUpDownCEndA.Value = dlg.Color.A;
                numericUpDownCEndR.Value = dlg.Color.R;
                numericUpDownCEndG.Value = dlg.Color.G;
                numericUpDownCEndB.Value = dlg.Color.B;
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            emits = new Emitter();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                imageTest = mTM.LoadTexture(dlg.FileName, 0);

                sFile = dlg.SafeFileName;
            }
            
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void EmitterInfo(Emitter emit, int iD)
        {
            emit.SParticleName =    textBoxParticleName.Text;
            emit.EShape =           (emitShape)comboBoxEmitterShape.SelectedIndex;
            emit.FMinLife =         (int)numericUpDownMinLife.Value;
            emit.FMaxLife =         (int)numericUpDownMaxLife.Value;
            emit.NMaxParticles =    (int)numericUpDownMaxParticles.Value;
            emit.FEmissionRate =    (float)numericUpDownEmissionRate.Value;
            emit.FRotationEnd =     (float)numericUpDownRotationEnd.Value;
            emit.FRotationStart =   (float)numericUpDownRotationStart.Value;
            emit.FScaleEnd =        (float)numericUpDownScaleEnd.Value;
            emit.FScaleStart =      (float)numericUpDownScaleStart.Value;
            emit.FVelocityEndX =    (float)numericUpDownVelocityXEnd.Value;
            emit.FVelocityStartX =  (float)numericUpDownVelocityXStart.Value;
            emit.FVelocityEndY =    (float)numericUpDownVelocityYEnd.Value;
            emit.FVelocityStartY =  (float)numericUpDownVelocityYStart.Value;
            //emit.CEndColor =        buttonColorEnd.BackColor;
            //emit.CStartColor = buttonColorStart.BackColor;
            emit.CEndColor = Color.FromArgb(
                                        (int)numericUpDownCEndA.Value,
                                        (int)numericUpDownCEndR.Value,
                                        (int)numericUpDownCEndG.Value,
                                        (int)numericUpDownCEndB.Value);
            emit.CStartColor = Color.FromArgb(
                                        (int)numericUpDownCStartA.Value,
                                        (int)numericUpDownCStartR.Value,
                                        (int)numericUpDownCStartG.Value,
                                        (int)numericUpDownCStartB.Value);

            emit.NShape =           comboBoxEmitterShape.SelectedIndex;
            
            emit.BIsLooping =       checkBoxLooping.Checked;
            emit.NEmitterID =       iD;
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();

            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";

            emits = new Emitter();
            EmitterInfo(emits, imageTest);

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = new XElement("Root");

                XElement xName = new XElement("FileName");
                xRoot.Add(xName);

                XAttribute xFName = new XAttribute("file", sFile);
                xName.Add(xFName);

                XElement xParticles = new XElement("Particles");
                xRoot.Add(xParticles);

                XElement xEmitter = new XElement("Emitter");
                xParticles.Add(xEmitter);

                XAttribute xEmitShape = new XAttribute("emitShape", emits.EShape);
                xEmitter.Add(xEmitShape);
                XAttribute xEName = new XAttribute("Name", emits.SParticleName);
                xEmitter.Add(xEName);
                XAttribute xIsLooping = new XAttribute("IsLooping", emits.BIsLooping);
                xEmitter.Add(xIsLooping);

                XElement xVelocity = new XElement("Velocity");
                xEmitter.Add(xVelocity);

                XAttribute xVelocityStartX = new XAttribute("vStartX", emits.FVelocityStartX);
                xVelocity.Add(xVelocityStartX);
                XAttribute xVelocityEndX = new XAttribute("vEndX", emits.FVelocityEndX);
                xVelocity.Add(xVelocityEndX);
                XAttribute xVelocityStartY = new XAttribute("vStartY", emits.FVelocityStartY);
                xVelocity.Add(xVelocityStartY);
                XAttribute xVelocityEndY = new XAttribute("vEndY", emits.FVelocityEndY);
                xVelocity.Add(xVelocityEndY);

                XElement xScale = new XElement("Scale");
                xEmitter.Add(xScale);

                XAttribute xScaleStart = new XAttribute("sStart", emits.FScaleStart);
                xScale.Add(xScaleStart);
                XAttribute xScaleEnd = new XAttribute("sEnd", emits.FScaleEnd);
                xScale.Add(xScaleEnd);

                XElement xColor = new XElement("Color");
                xEmitter.Add(xColor);

                XAttribute xColorStartA = new XAttribute("cStartA", emits.CStartColor.A);
                xColor.Add(xColorStartA);
                XAttribute xColorStartR = new XAttribute("cStartR", emits.CStartColor.R);
                xColor.Add(xColorStartR);
                XAttribute xColorStartG = new XAttribute("cStartG", emits.CStartColor.G);
                xColor.Add(xColorStartG);
                XAttribute xColorStartB = new XAttribute("cStartB", emits.CStartColor.B);
                xColor.Add(xColorStartB);

                XAttribute xColorEndA = new XAttribute("cEndA", emits.CEndColor.A);
                xColor.Add(xColorEndA);
                XAttribute xColorEndR = new XAttribute("cEndR", emits.CEndColor.R);
                xColor.Add(xColorEndR);
                XAttribute xColorEndG = new XAttribute("cEndG", emits.CEndColor.G);
                xColor.Add(xColorEndG);
                XAttribute xColorEndB = new XAttribute("cEndB", emits.CEndColor.B);
                xColor.Add(xColorEndB);

                XElement xEmission = new XElement("Emission");
                xEmitter.Add(xEmission);

                XAttribute xEmissionRate = new XAttribute("emissionRate", emits.FEmissionRate);
                xEmission.Add(xEmissionRate);

                XElement xRotation = new XElement("Rotation");
                xEmitter.Add(xRotation);

                XAttribute xRotationStart = new XAttribute("rotateStart", emits.FRotationStart);
                xRotation.Add(xRotationStart);
                XAttribute xRotationEnd = new XAttribute("rotateEnd", emits.FRotationEnd);
                xRotation.Add(xRotationEnd);

                XElement xLifetime = new XElement("Lifetime");
                xEmitter.Add(xLifetime);

                XAttribute xLifetimeMin = new XAttribute("minLife", emits.FMinLife);
                xLifetime.Add(xLifetimeMin);
                XAttribute xLifetimeMax = new XAttribute("maxLife", emits.FMaxLife);
                xLifetime.Add(xLifetimeMax);

                XElement xShape = new XElement("Shape");
                xEmitter.Add(xShape);

                XAttribute xNShape = new XAttribute("nShape", emits.NShape);
                xShape.Add(xNShape);

                XElement xMaxParticles = new XElement("MaxParticles");
                xEmitter.Add(xMaxParticles);

                XAttribute xNMaxParticles = new XAttribute("nMaxParticles", emits.NMaxParticles);
                xMaxParticles.Add(xNMaxParticles);

                xRoot.Save(dlg.FileName);
            }
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = XElement.Load(dlg.FileName);

                XElement xFile = xRoot.Element("FileName");

                XAttribute xFileName = xFile.Attribute("file");
                sFile = xFileName.Value;
                
                // Loading image relative
                imageTest = mTM.LoadTexture(workingDirectory + "\\" + sFile, 0);

                emits.NEmitterID = imageTest;

                
                XElement xParticles = xRoot.Element("Particles");
                XElement xEmitter = xParticles.Element("Emitter");
                XAttribute xEmitShape = xEmitter.Attribute("emitShape");
                emits.EShape = (emitShape) Enum.Parse(typeof(emitShape), xEmitShape.Value);
         
                XAttribute xName = xEmitter.Attribute("Name");
                emits.SParticleName = xName.Value;
                textBoxParticleName.Text = xName.Value;

                XAttribute xIsLooping = xEmitter.Attribute("IsLooping");
                emits.BIsLooping = Convert.ToBoolean(xIsLooping.Value);
                checkBoxLooping.Checked = Convert.ToBoolean(xIsLooping.Value);

                XElement xVelocity = xEmitter.Element("Velocity");
                XAttribute xVStartX = xVelocity.Attribute("vStartX");
                emits.FVelocityStartX = float.Parse(xVStartX.Value);
                XAttribute xVEndX = xVelocity.Attribute("vEndX");
                emits.FVelocityEndX = float.Parse(xVEndX.Value);
                XAttribute xVStartY = xVelocity.Attribute("vStartY");
                emits.FVelocityStartY = float.Parse(xVStartY.Value);
                XAttribute xVEndY = xVelocity.Attribute("vEndY");
                emits.FVelocityEndY = float.Parse(xVEndY.Value);
                numericUpDownVelocityXEnd.Value = decimal.Parse(xVEndX.Value);
                numericUpDownVelocityXStart.Value = decimal.Parse(xVStartX.Value);
                numericUpDownVelocityYEnd.Value = decimal.Parse(xVEndY.Value);
                numericUpDownVelocityYStart.Value = decimal.Parse(xVStartY.Value);

                XElement xScale = xEmitter.Element("Scale");
                XAttribute xScaleStart = xScale.Attribute("sStart");
                emits.FScaleStart = float.Parse(xScaleStart.Value);
                numericUpDownScaleStart.Value = decimal.Parse(xScaleStart.Value);
                XAttribute xScaleEnd = xScale.Attribute("sEnd");
                emits.FScaleEnd = float.Parse(xScaleEnd.Value);
                numericUpDownScaleEnd.Value = decimal.Parse(xScaleEnd.Value);

                int cStartA, cStartR, cStartG, cStartB;
                XElement xColor = xEmitter.Element("Color");
                XAttribute xCStartA = xColor.Attribute("cStartA");
                cStartA = int.Parse(xCStartA.Value);
                XAttribute xCStartR = xColor.Attribute("cStartR");
                cStartR = int.Parse(xCStartR.Value);
                XAttribute xCStartG = xColor.Attribute("cStartG");
                cStartG = int.Parse(xCStartG.Value);
                XAttribute xCStartB = xColor.Attribute("cStartB");
                cStartB = int.Parse(xCStartB.Value);

                emits.CStartColor = Color.FromArgb(cStartA, cStartR, cStartG, cStartB);
                buttonColorStart.BackColor = emits.CStartColor;
                numericUpDownCStartA.Value = buttonColorStart.BackColor.A;
                numericUpDownCStartR.Value = buttonColorStart.BackColor.R;
                numericUpDownCStartG.Value = buttonColorStart.BackColor.G;
                numericUpDownCStartB.Value = buttonColorStart.BackColor.B;

                int cEndA, cEndR, cEndG, cEndB;
                XAttribute xCEndA = xColor.Attribute("cEndA");
                cEndA = int.Parse(xCEndA.Value);
                XAttribute xCEndR = xColor.Attribute("cEndR");
                cEndR = int.Parse(xCEndR.Value);
                XAttribute xCEndG = xColor.Attribute("cEndG");
                cEndG = int.Parse(xCEndG.Value);
                XAttribute xCEndB = xColor.Attribute("cEndB");
                cEndB = int.Parse(xCEndB.Value);

                emits.CEndColor = Color.FromArgb(cEndA, cEndR, cEndG, cEndB);
                buttonColorEnd.BackColor = emits.CEndColor;
                numericUpDownCEndA.Value = buttonColorEnd.BackColor.A;
                numericUpDownCEndR.Value = buttonColorEnd.BackColor.R;
                numericUpDownCEndG.Value = buttonColorEnd.BackColor.G;
                numericUpDownCEndB.Value = buttonColorEnd.BackColor.B;
                
                XElement xEmissionRate = xEmitter.Element("Emission");
                XAttribute xEmission = xEmissionRate.Attribute("emissionRate");
                emits.FEmissionRate = float.Parse(xEmission.Value);
                numericUpDownEmissionRate.Value = decimal.Parse(xEmission.Value);

                XElement xRotation = xEmitter.Element("Rotation");
                XAttribute xRotateStart = xRotation.Attribute("rotateStart");
                emits.FRotationStart = float.Parse(xRotateStart.Value);
                numericUpDownRotationStart.Value = decimal.Parse(xRotateStart.Value);
                XAttribute xRotateEnd = xRotation.Attribute("rotateEnd");
                emits.FRotationEnd = float.Parse(xRotateEnd.Value);
                numericUpDownRotationEnd.Value = decimal.Parse(xRotateEnd.Value);

                XElement xLifetime = xEmitter.Element("Lifetime");
                XAttribute xMinLife = xLifetime.Attribute("minLife");
                emits.FMinLife = float.Parse(xMinLife.Value);
                numericUpDownMinLife.Value = decimal.Parse(xMinLife.Value);
                XAttribute xMaxLife = xLifetime.Attribute("maxLife");
                emits.FMaxLife = float.Parse(xMaxLife.Value);
                numericUpDownMaxLife.Value = decimal.Parse(xMaxLife.Value);

                XElement xShape = xEmitter.Element("Shape");
                XAttribute xNShape = xShape.Attribute("nShape");
                emits.NShape = int.Parse(xNShape.Value);
                comboBoxEmitterShape.SelectedIndex = int.Parse(xNShape.Value);

                XElement xMaxParts = xEmitter.Element("MaxParticles");
                XAttribute xMaxParticles = xMaxParts.Attribute("nMaxParticles");
                emits.NMaxParticles = int.Parse(xMaxParticles.Value);
                numericUpDownMaxParticles.Value = decimal.Parse(xMaxParticles.Value);
            }
        }

        private void splitContainer2_Panel2_MouseDown(object sender, MouseEventArgs e)
        {
            mouseDown = true;
        }

        private void splitContainer2_Panel2_MouseUp(object sender, MouseEventArgs e)
        {
            mouseDown = false;
        }

        private void splitContainer2_Panel2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseDown)
            {
                Point newPt = new Point(e.X, e.Y);
                emits.PtMouse = newPt;
            }
        }
    }
}
